// $Id: interface_proxy.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPCOM_PROXY_INTERFACE_PROXY_HPP
#define XPCOM_PROXY_INTERFACE_PROXY_HPP

#include <xpcom/config.hpp>
#include <xpcom/types.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

namespace xpcom {

template <typename T>
class ptr_base;

namespace proxy {

//
// Provides a proxy of interface, and provides more convenience methods.
// By default, interface_proxy inherits from T, so it can be used as the
// original type.
//
// This class is typically used with ref_ptr/noref_ptr.
//
template <typename T, typename Base = T>
class interface_proxy : public Base
{
private:
    interface_proxy();
    interface_proxy(const interface_proxy&);
    const interface_proxy& operator=(const interface_proxy&);

    // The three functions of interface are hidden
    XPCOM_METHOD query_interface(const uuid&, void**);
    XPCOM_METHOD_(refcnt_t) add_ref();
    XPCOM_METHOD_(refcnt_t) release();
};

//
// Specialized interface_proxy for root interface.
// Every interface_proxy specialization should inherit from this one, directly
// or indirectly.
//
#ifdef XPCOM_USE_INHERITED_INTERFACE_PROXY

template <typename Base>
class interface_proxy<interface, Base> : protected Base
{
protected:
    // Access the base pointer
    XPCOM_FORCEINLINE
    Base* _base()
    {
        return static_cast<Base*>(this);
    }

private:
    interface_proxy();
    interface_proxy(const interface_proxy&);
    const interface_proxy& operator=(const interface_proxy&);

    friend class ptr_base<Base>;
};

#else // XPCOM_USE_INHERITED_INTERFACE_PROXY

template <typename Base>
class interface_proxy<interface, Base>
{
protected:
    // Access the base pointer
    XPCOM_FORCEINLINE
    Base* _base()
    {
        return reinterpret_cast<Base*>(this);
    }

private:
    interface_proxy();
    interface_proxy(const interface_proxy&);
    const interface_proxy& operator=(const interface_proxy&);
};

#endif // XPCOM_USE_INHERITED_INTERFACE_PROXY

} // namespace xpcom::proxy
} // namespace xpcom

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // XPCOM_PROXY_INTERFACE_PROXY_HPP
